/////////////////////////////////////////////////////////////////////////
//
// Amuse Engine - graphics
// Copyright (c) 2014.  All Rights Reserved
//
// File:		AEContextViewProperties.h
// Author:		Gianluca Belardelli
// Date:		12/12/2014
//
/////////////////////////////////////////////////////////////////////////
#ifndef _AECONTEXTVIEWPROPERTIES_H_
#define _AECONTEXTVIEWPROPERTIES_H_

/// \brief
///  A class that holds context properties such as FOV or clip planes required for computing the projection matrix.
///
/// This class can be shared by multiple contexts to keep projection properties synchronized.
class AEContextViewProperties : public AEReferencedObject
{
// Members
private:
	AEProjectionType	m_eProjectionType;
	AEBOOL32 			m_bIsDirty;
	
	AEFLOAT32 			m_fNear;
	AEFLOAT32 			m_fFar;
	
	AEFLOAT32 			m_fFovX;
	AEFLOAT32 			m_fFovY;
	AEFLOAT32 			m_fDisplayAspectRatio;
	AEFLOAT32 			m_fLODScale;
	
	AEFLOAT32 			m_fOrthographicWidth;
	AEFLOAT32 			m_fOrthographicHeight;
	
	// The cached projection matrix, as well as a version that flips the y-coordinate
	AEMatrix4f 			m_matCachedMatrix[2];
  
// Methods
public:
	/// \brief Constructor.
	AE_DLLIMPEXP AEContextViewProperties( void );
	
	/// \brief Returns the computed projection matrix.
	///
	/// \param yRange
	///   Supply hkvClipSpaceYRange::OneToMinusOne to retrieve a projection that flips the y screen space coordinate.
	AE_DLLIMPEXP const AEMatrix4f &GetProjectionMatrix( AEClipSpaceYRange::Enum yRange = AEClipSpaceYRange::MinusOneToOne );
	
	/// \brief Sets the projection type to be used to compute the projection matrix.
	AE_DLLIMPEXP void SetProjectionType( AEProjectionType eType );
	
	/// \brief Returns the previously set projection type.
	AE_FORCEINLINE AEProjectionType GetProjectionType( void );
	
	/// \brief Supplies a custom projection matrix to be used when the projection type is VIS_PROJECTIONTYPE_CUSTOM.
	AE_DLLIMPEXP void SetCustomProjection( const AEMatrix4f &matProjection );
	
	/// \brief Sets the field of view to be used when the projection type is VIS_PROJECTIONTYPE_PERSPECTIVE.
	///
	/// If either FOV value is 0.0f, it will be computed automatically using the other value and the current
	/// display aspect ratio.
	///
	/// \param fFovX
	///   The horizontal field of view angle in degrees. Use 0.0f to derive it from fFovY via the display aspect ratio.
	///
	/// \param fFovY
	///   The vertical field of view angle in degrees. Use 0.0f to derive it from fFovX via the display aspect ratio.
	AE_DLLIMPEXP void SetFov( AEFLOAT32 fFovX, AEFLOAT32 fFovY );
	
	/// \brief Retrieves the horizontal and vertical FOV angle previously set.
	AE_DLLIMPEXP void GetFov( AEFLOAT32 &fFovX, AEFLOAT32 &fFovY ) const;
	
	/// \brief Retrieves non-zero horizontal and vertical FOV angles by computing previously set zero values from the display aspect ratio.
	AE_DLLIMPEXP void GetFinalFov( AEFLOAT32 &fFovX, AEFLOAT32 &fFovY ) const;
	
	/// \brief Retrieves the horizontal FOV angle previously set.
	AE_DLLIMPEXP AEFLOAT32 GetFovX( void ) const;
	
	/// \brief Retrieves the vertical FOV angle previously set.
	AE_DLLIMPEXP AEFLOAT32 GetFovY( void ) const;
	
	/// \brief Sets the display aspect ratio to be used for auto-FOV computation.
	///
	/// By default, it is set to the current display device's physical aspect ratio.
	///
	/// \param fDisplayAspectRatio
	///   The display aspect ratio that is to be used. The value is defined by width / height.
	AE_DLLIMPEXP void SetDisplayAspectRatio( AEFLOAT32 fDisplayAspectRatio );
	
	/// \brief Returns the display aspect ratio used for auto-FOV computation.
	AE_DLLIMPEXP AEFLOAT32 GetDisplayAspectRatio( void ) const;
	
	/// \brief Sets the near plane to be used when the projection type is VIS_PROJECTIONTYPE_ORTHOGRAPHIC or VIS_PROJECTIONTYPE_PERSPECTIVE.
	AE_DLLIMPEXP void SetNear( AEFLOAT32 fNear );
	
	/// \brief Sets the far plane to be used when the projection type is VIS_PROJECTIONTYPE_ORTHOGRAPHIC or VIS_PROJECTIONTYPE_PERSPECTIVE.
	AE_DLLIMPEXP void SetFar( AEFLOAT32 fFar );
	
	/// \brief Sets the clip planes to be used when the projection type is VIS_PROJECTIONTYPE_ORTHOGRAPHIC or VIS_PROJECTIONTYPE_PERSPECTIVE.
	AE_DLLIMPEXP void SetClipPlanes( AEFLOAT32 fNear, AEFLOAT32 fFar );
	
	/// \brief Returns the near plane value previously set.
	AE_DLLIMPEXP AEFLOAT32 GetNear( void ) const;
	
	/// \brief Returns the far plane value previously set.
	AE_DLLIMPEXP AEFLOAT32 GetFar( void ) const;
	
	/// \brief Retrieves the clip plane values previously set.
	AE_DLLIMPEXP void GetClipPlanes( AEFLOAT32 &fNear, AEFLOAT32 &fFar) const;
	
	/// \brief Sets the scaling value for LOD clipping. Values larger than 1.0 cause more aggressive clipping. A value of 0.0 turns off LOD changes and far clipping whatsoever
	AE_DLLIMPEXP void SetLODScaling( AEFLOAT32 fScale );
	
	/// \brief Returns the LOD scaling value previously set.
	AE_DLLIMPEXP AEFLOAT32 GetLODScaling( void ) const;

	/// \brief Sets the projection width and height to be used when the projection type is VIS_PROJECTIONTYPE_ORTHOGRAPHIC.
	AE_DLLIMPEXP void SetOrthographicSize( AEFLOAT32 fWidth, AEFLOAT32 fHeight );
	
	/// \brief Sets the projection width to be used when the projection type is VIS_PROJECTIONTYPE_ORTHOGRAPHIC.
	AE_DLLIMPEXP void SetOrthographicWidth( AEFLOAT32 fWidth );
	
	/// \brief Sets the projection height to be used when the projection type is VIS_PROJECTIONTYPE_ORTHOGRAPHIC.
	AE_DLLIMPEXP void SetOrthographicHeight( AEFLOAT32 fHeight );
	
	/// \brief Returns the projection width previously set.
	AE_DLLIMPEXP AEFLOAT32 GetOrthographicWidth( void );
	
	/// \brief Returns the projection height previously set.
	AE_DLLIMPEXP AEFLOAT32 GetOrthographicHeight( void );
};

#include "AEContextViewProperties.inl"

#endif // _AECONTEXTVIEWPROPERTIES_H_
